#pragma once
#include<iostream>
#include<fstream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cstdarg>
#include<sys/types.h>
#include<unistd.h>
#include<pthread.h>
#include"LockGuard.hpp"

bool gIsSave = false;
const std::string logname = "log.txt";

enum Level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};
void SaveFile(const std::string &filename,const std::string &message)
{
    std::ofstream out(filename,std::ios::app);
    if(!out.is_open())
    {
        return;
    }
    out<<message;
    out.close();
}

std:: string LevelToString(int level)
{
    switch (level)
    {
    case DEBUG:
        return "DEBUG";
    case INFO:
        return "INFO";
    case WARNING:
        return "WARNING";
    case ERROR:
        return "ERROR";
    case FATAL:
        return "FATAL";
    
    default:
        return "Unknown";
    }
}
 std::string GETIMESTRING()
    {
        time_t curr_time = time(nullptr);
        struct tm *format_time = localtime(&curr_time);
        if(format_time ==nullptr)
        {
            return "None";
        }
        char time_buffer[1024];
        snprintf(time_buffer,sizeof(time_buffer),"%d-%d-%d %d:%d:%d",
                format_time->tm_year+1900,
                format_time->tm_mon+1,
                format_time->tm_mday,
                format_time->tm_hour,
                format_time->tm_min,
                format_time->tm_sec);
                return time_buffer;
    }
    // 全局锁
    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

    //显示行号，内容时间
void LogMessage(std::string filename,int linem,bool issave,int level,const char *format, ...)
{
    std::string levelstr =LevelToString(level);
    std::string timestr = GETIMESTRING();
    pid_t selfid = getpid();

    char buffer[1024];
    va_list arg;
    va_start(arg,format);
    vsnprintf(buffer,sizeof(buffer),format,arg);
    va_end(arg);

    std::string message = "["+timestr +"]" + "[" +levelstr+"]" +"["
    +std::to_string(selfid)+"]" +"["+filename+"]" + "["+std::to_string(linem)+"]"+buffer;
    LockGuard lockguard(&lock);
    if(!issave)
    {
        std::cout<<message;
    }
    else
    {
        SaveFile(logname,message);
    }
}

#define LOG(Level,format,...)                                \
do                                                           \
{                                                            \
    LogMessage(__FILE__,__LINE__,gIsSave,Level,format,##__VA_ARGS__);\
}while(0)
#define EnableFile()                    \
do                                      \
{                                       \
  gIsSave = true;                       \
} while (0);

#define EnableScreen()                  \
do                                      \
{                                       \
    gIsSave = false                     \
} while (0);                            
